home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / mint / lib / mntlib44.zoo / mntlib / buffindf.c < prev    next >
C/C++ Source or Header  |  1994-01-16  |  3KB  |  130 lines

  1. /* _buffindfile: given a base filename, a list of directories, and a list
  2.    of possible extensions to the filename, attempts to find a file.
  3.    Useful for doing, e.g. spawnvp. Note that the current directory
  4.    is always searched first! If the filename already contains a
  5.    path specification (or extension) then the given path list
  6.    (or extension list) is ignored.
  7.    Returns the name by which the file was found, or NULL.
  8.  
  9.    Written by Eric R. Smith and placed in the public domain.
  10.  
  11.    rehacked by Uwe Ohse, 28.4.93, to support reentrant spawn/popen.
  12.  
  13.    19.12.93, Andreas Schwab, clean up namespace:
  14.    - findfile moved to separate file
  15.    - buffindfile renamed to _buffindfile
  16. */
  17.  
  18. #include <compiler.h>
  19. #include <support.h>
  20. #include <stddef.h>
  21. #include <types.h>
  22. #include <stat.h>
  23. #include <string.h>
  24.  
  25. /* characters used to separate components in a path list */
  26. #define PATHSEP1        ':'
  27. #define PATHSEP2        ','
  28.  
  29. /* characters used to separate directory names in a file */
  30. #define DIRSEP1         '\\'    /* native OS directory separator */
  31. #define DIRSEP2         '/'     /* for emulating another OS */
  32.  
  33. static char *const nullext[] = { NULL };
  34.  
  35. static int EXISTS __PROTO((const char *));
  36.  
  37. static int
  38. EXISTS(name)
  39.     const char *name;
  40. {
  41.     struct stat dummy;
  42.  
  43.     if (stat(name, &dummy) != 0)
  44.         return 0;
  45.     if ( (dummy.st_mode & S_IFMT) != S_IFREG )
  46.         return 0;
  47.     return 1;
  48. }
  49.  
  50.  
  51. char *
  52. _buffindfile(fname, fpath, fext, try)
  53.       const char *fname, *fpath;
  54.       char *const *fext, *try;
  55. {
  56.       char *s, *extplace, *const *nextext, c;
  57.       const char *t;
  58.       int  hasext = 0, haspath = 0;
  59.  
  60.     if (!fname || !*fname)
  61.         return NULL;
  62.  
  63.       s = try; t = fname;
  64.  
  65. /* copy the file in, checking to see if a path and/or extension are already
  66.    given */
  67.  
  68.       while ( (c = *t++) != 0 )
  69.       {
  70.               if (c == DIRSEP1 || c == DIRSEP2)
  71.               {
  72.                       haspath = 1;
  73.                       hasext = 0;
  74.               }
  75.               else if (c == '.')
  76.                       hasext = 1;
  77.               *s++ = c;
  78.       }
  79.       extplace = s;
  80.       *s = 0;
  81.  
  82.       if (haspath || !fpath)
  83.               fpath = "";
  84.       if (hasext || !fext)
  85.               fext = nullext;
  86.  
  87.       for(;;) {               /* loop on path elements */
  88.               nextext = fext;
  89.         if (!hasext) {
  90.             extplace[0] = 0;
  91.             extplace[1] = 0;
  92.         }
  93.  
  94.         if (EXISTS(try))
  95.             return try;
  96.         extplace[0] = '.';
  97.               while(*nextext) {       /* loop on extensions */
  98.                       (void)strcpy(&extplace[1], *nextext++);
  99.                       if (EXISTS(try))
  100.                               return try;
  101.               }
  102.               if (!*fpath) break;  /* no more places to look */
  103.  
  104. /* copy in next element of path list */
  105.               s = try;
  106.         /* an attempt to accomodate within reason TOS specs  -- mj */
  107.         if (*(fpath + 1) == ':') {
  108.             if ((*(fpath + 2) == DIRSEP1 ||
  109.                  *(fpath + 2) == DIRSEP2)   &&
  110.                 (*fpath != '.' && *fpath != ':')) {
  111.                 *s++ = *fpath++;
  112.                 *s++ = *fpath++;
  113.                 *s++ = *fpath++;
  114.             }
  115.         }
  116.               while ((c = *fpath) != 0 && c != PATHSEP1 && c != PATHSEP2) {
  117.                       *s++ = c;
  118.                       fpath++;
  119.               }
  120.               if (c)
  121.                       fpath++;
  122.               *s++ = DIRSEP1;
  123.               t = fname;
  124.               while ((*s++ = *t++) != 0)
  125.                       ;
  126.               extplace = --s ;        /* where the extension gets written */
  127.       }
  128.       return NULL;
  129. }
  130.